package com.open.capacity.salary.controller;

import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.open.capacity.annotation.log.LogAnnotation;
import com.open.capacity.commons.Result;
import com.open.capacity.salary.dto.GridHeadDataDto;
import com.open.capacity.salary.dto.GzRecordSalaryDto;
import com.open.capacity.salary.dto.ImportResult;
import com.open.capacity.salary.entity.GzItem;
import com.open.capacity.salary.entity.GzZt;
import com.open.capacity.salary.service.GzEnableMonthService;
import com.open.capacity.salary.service.GzItemService;
import com.open.capacity.salary.service.GzZtService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;
import com.open.capacity.salary.entity.GzRecordSalary;
import com.open.capacity.salary.service.GzRecordSalaryService;

import com.open.capacity.commons.PageResult;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

/**
 * 工资系统工资录入表
 *
 * @author
 * @email
 * @date 2021-08-02 14:26:51
 */
@Slf4j
@RestController
@RequestMapping("gzrecordsalarys")
@Api(tags = "工资系统工资录入表")
public class GzRecordSalaryController {

    @Autowired
    private GzRecordSalaryService gzRecordSalaryService;

    @Autowired
    private GzItemService gzItemService;

    @Autowired
    private GzZtService ztService;

    @Autowired
    private GzEnableMonthService gzEnableMonthService;


    /**
     * 列表
     */
    @RequestMapping("/page")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:list')")
    public PageResult page(@RequestParam Map<String, Object> params) {
        PageResult pageResult = gzRecordSalaryService.pageAll(params);
        return pageResult;
    }

    /**
     * 列表
     */
    @RequestMapping("/list")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:list')")
    public Result list(@RequestParam Map<String, Object> params) {
        List<Map<String, Object>> list = gzRecordSalaryService.findAll(params);
        return Result.succeed(list);
    }

    /**
     * 工资录入表头
     */
    @RequestMapping("/header")
    public Result<GridHeadDataDto> header(@RequestParam Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        String editable = params.get("editable").toString();

        TreeMap<Integer, GridHeadDataDto.ColData> hsColMap = new TreeMap<>();

        GridHeadDataDto data = new GridHeadDataDto();

        List<GridHeadDataDto.ColData> colDatas = new ArrayList<>();
        List<String> colNames = new ArrayList<>();

        GridHeadDataDto.ColData departmentName = new GridHeadDataDto.ColData.Builder().label("部门").name("departmentname").align("center").width(120).sort(true).frozen(true).build();
        GridHeadDataDto.ColData userCode = new GridHeadDataDto.ColData.Builder().label("员工编号").name("usercode").align("center").width(80).sort(true).frozen(true).sort(false).build();
        GridHeadDataDto.ColData userName = new GridHeadDataDto.ColData.Builder().label("姓名").name("username").align("center").width(100).sort(true).frozen(true).build();

        hsColMap.put(1, departmentName);
        hsColMap.put(2, userCode);
        hsColMap.put(3, userName);

        int index = 4;


        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        GridHeadDataDto.ColData.Builder.Edit edit = new GridHeadDataDto.ColData.Builder.Edit();
        edit.setType("number");
        edit.setChange("function (data, num) { }");

        for (GzItem item : itemList) {
            if (editable.equals("1")) {
                GridHeadDataDto.ColData col = new GridHeadDataDto.ColData.Builder()
                        .label(item.getName())
                        .name("col_" + item.getId())
                        .align("right")
                        .statistics(true)
                        .sort(true)
                        .formatter("function (cellvalue) { return $.formatMoney(cellvalue, 2)}")
                        .edit(edit)
                        .width(120).build();
                hsColMap.put(index++, col);
            } else {
                GridHeadDataDto.ColData col = new GridHeadDataDto.ColData.Builder()
                        .label(item.getName())
                        .name("col_" + item.getId())
                        .align("right")
                        .statistics(true)
                        .sort(true)
                        .formatter("function (cellvalue) { return $.formatMoney(cellvalue, 2)}")
                        .width(120).build();
                hsColMap.put(index++, col);
            }

            colNames.add("col_" + item.getId());
        }

        //GridHeadDataDto.ColData description = new GridHeadDataDto.ColData.Builder().label("备注").name("description").align("left").width(100).build();
        GridHeadDataDto.ColData id = new GridHeadDataDto.ColData.Builder().label("id").name("id").align("center").width(1).hidden(true).build();
        //hsColMap.put(index++, description);
        hsColMap.put(index++, id);

        //保证有序
        for (Map.Entry<Integer, GridHeadDataDto.ColData> m : hsColMap.entrySet()) {
            GridHeadDataDto.ColData val = m.getValue();
            colDatas.add(val);
        }
        data.setColData(colDatas);
        data.setColNames(colNames);
        return Result.succeed(data, "成功");
    }

    /**
     * 查询单条记录
     */
    @RequestMapping("/findById")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:list')")
    public Result findById(String id) {
        return Result.succeed(gzRecordSalaryService.findById(id));
    }


    /**
     * 查询个人工资
     */
    @RequestMapping("/findByUserid")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:list')")
    public Result findByUserid(String companyId, String ztId, String userid) {
        List<Map<String, Object>> list = gzRecordSalaryService.findByUserid(companyId, ztId, userid);
        return Result.succeed(list);
    }

    /**
     * 保存
     */
    @RequestMapping("/saveOrUpdate1")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:save')")
    public Result saveOrUpdate1(@RequestBody @Valid GzRecordSalaryDto gzRecordSalary) {
        gzRecordSalaryService.save(gzRecordSalary);
        return Result.succeed("保存成功");
    }

    /**
     * 批量保存
     */
    @RequestMapping("/saveOrUpdate2")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:save')")
    public Result saveOrUpdate2(String companyId, String ztId, @RequestBody @Valid List<GzRecordSalary> list) {
        gzRecordSalaryService.batchSave(companyId, ztId, list);
        return Result.succeed("保存成功");
    }


    /**
     * 批量调整
     */
    @RequestMapping("/edit")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:save')")
    public Result edit(String companyId, String ztId, String operate, String itemId, BigDecimal money) {
        gzRecordSalaryService.edit(companyId, ztId, operate, itemId, money);
        return Result.succeed("修改成功");
    }

    /**
     * 批量根据公式计算款项工资
     */
    @RequestMapping("/calc")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:calc')")
    public Result calc(String companyId, String ztId) {
        gzRecordSalaryService.calc(companyId, ztId);
        return Result.succeed("计算完成");
    }

    /**
     * 删除不在账套内的用户记录
     */
    @RequestMapping("/deleteNotInZtUser")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:deleteNotInZtUser')")
    public Result deleteNotInZtUser(String companyId, String ztId, String month) {
        gzRecordSalaryService.deleteNotInZtUser(companyId, ztId, month);
        return Result.succeed("执行成功");
    }


    /**
     * 删除
     */
    @DeleteMapping("/delete/{id}")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:delete')")
    public Result delete(@PathVariable String id) {
        gzRecordSalaryService.delete(id);
        return Result.succeed("删除成功");
    }

    /**
     * 获取标签页名称
     */
    @PostMapping("/getExcelSheets")
    public Result getExcelSheets(@RequestParam("file") MultipartFile multipartFile) throws Exception {
        List<String> result = gzRecordSalaryService.getExcelSheets(multipartFile);
        return Result.succeed(result);
    }


    /**
     * 导入excel
     */
    @PostMapping("/importExcel")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:import')")
    public Result importExcel(String companyId, String ztId, String category, String sheet, @RequestParam("file") MultipartFile multipartFile) throws Exception {
        long count = gzRecordSalaryService.importExcel(companyId, ztId, category, sheet, multipartFile);
        ImportResult result = new ImportResult();
        result.setCount(count);
        return Result.succeed(result, "导入成功");
    }


    /**
     * 导入excel(海珠统发模板)
     */
    @PostMapping("/importExcelExt")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:import')")
    public Result importExcelExt(String companyId, String ztId, String category, String sheet, @RequestParam("file") MultipartFile multipartFile) throws Exception {
        ImportResult result = gzRecordSalaryService.importExcelExt(companyId, ztId, category, sheet, multipartFile);
        return Result.succeed(result, "导入成功");
    }

    /**
     * 导出
     *
     * @return
     */
    @GetMapping("/exportExcel")
    @PreAuthorize("hasAnyAuthority('gz_record_salary:gzrecordsalary:export')")
    public void export(@RequestParam Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        GzZt zt = ztService.findById(ztId);
        //账套当前月份
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();
        String fileName = zt.getName() + "(" + currentMonth + ")";

        List<Map<String, Object>> resList = gzRecordSalaryService.findAll(params);
        //封装表头
        List<ExcelExportEntity> headList = new ArrayList<>();
        ExcelExportEntity excelExportEntity;

        /**
         * name : "姓名"    ---> 表头显示    key是属性映射（后面会用到，key任意配置，但不要在同一个方法中重复）
         * excelExportEntity.setWidth(30);    --->  设置单元格宽度
         * excelExportEntity.setNeedMerge(true);   --->  开启单元格合并，这个属性的开启并不会产生影响，因为没有配置合并条件
         * */

        excelExportEntity = new ExcelExportEntity("部门", "departmentname");
        excelExportEntity.setWidth(15);
        excelExportEntity.setNeedMerge(true);
        excelExportEntity.setMergeVertical(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("员工编号", "usercode");
        excelExportEntity.setWidth(10);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("姓名", "username");
        excelExportEntity.setWidth(12);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("身份证号", "code");
        excelExportEntity.setWidth(20);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        //遍历动态表头
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);

        if (params.containsKey("columns") && StringUtils.isNotEmpty(params.get("columns").toString())) { //选择列导出
            List<String> columnList = Arrays.asList(params.get("columns").toString().split(","));
            for (GzItem dynamicCol : itemList) {
                if (columnList.contains(dynamicCol.getName())) {
                    excelExportEntity = new ExcelExportEntity(dynamicCol.getName(), "col_" + dynamicCol.getId());
                    excelExportEntity.setType(10);
                    excelExportEntity.setNumFormat("0.00");
                    headList.add(excelExportEntity);
                }
            }
        } else {
            for (GzItem dynamicCol : itemList) {
                excelExportEntity = new ExcelExportEntity(dynamicCol.getName(), "col_" + dynamicCol.getId());
                excelExportEntity.setType(10);
                excelExportEntity.setNumFormat("0.00");
                headList.add(excelExportEntity);
            }
        }

        //"封装"数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> dataMap;
        //循环封装数据
        for (Map<String, Object> element : resList) {
            dataMap = new HashMap<>();
            dataMap.put("departmentname", element.get("departmentname"));
            dataMap.put("usercode", element.get("usercode"));
            dataMap.put("username", element.get("username"));
            dataMap.put("code", element.get("code"));

            for (GzItem col : itemList) {
                if (element.containsKey("col_" + col.getId())) {
                    dataMap.put("col_" + col.getId(), element.get("col_" + col.getId()));
                }
            }
            dataList.add(dataMap);
        }
        //导出
        if (CollectionUtils.isNotEmpty(dataList)) {
            response.setContentType("application/vnd.ms-excel");
            try {
                response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO8859-1") + ".xls");
            } catch (UnsupportedEncodingException e) {
                log.error(e.toString());
            }
            OutputStream ouputStream = null;
            ExportParams param = new ExportParams(null, currentMonth);
            Workbook workbook = ExcelExportUtil.exportExcel(param, headList, dataList);
            try {
                ouputStream = response.getOutputStream();
                workbook.write(ouputStream);
            } catch (Exception e) {
                log.error(e.toString());
                throw new RuntimeException("系统异常");
            } finally {
                try {
                    if (ouputStream != null) {
                        ouputStream.flush();
                        ouputStream.close();
                    }
                } catch (Exception e) {
                    log.error(e.toString());
                    throw new RuntimeException("系统异常");
                }
            }
        }
    }
}
